﻿using IGeekFan.AspNetCore.Knife4jUI;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Workflow2211A.API;
using Workflow2211A.Application;
using Workflow2211A.Application.Services;
using Workflow2211A.Application.Services.IndependentBilling;
using Workflow2211A.Application.Steps;
using Workflow2211A.Domain;
using WorkflowCore.Persistence.EntityFramework.Services;
using Yitter.IdGenerator;
//创建一个默认的应用构建器，自动加载配置文件如 appsettings.json，并提供依赖注入和其他参数
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
//添加控制器支持，启用 MVC 模式处理 HTTP 请求
builder.Services.AddControllers();
//添加 Swagger/OpenAPI 文档工具，自动生成 API 文档
//潜在问题：Swagger 默认依赖 XML 注释，如果您未调用 SwaggerGenOptions.IncludeXmlComments，可能导致文档缺失或不完整
builder.Services.AddSwaggerGen(x => 
{
    var path = AppDomain.CurrentDomain.BaseDirectory + "Workflow2211A.API.xml";
    var appPath = AppDomain.CurrentDomain.BaseDirectory + "Workflow2211A.Application.xml";
    x.IncludeXmlComments(path,true);
    x.IncludeXmlComments(appPath, true);
});
//注册仓储
builder.Services.AddScoped(typeof(IBaseRepository<>),typeof(BaseRepository<>));

//builder.Services.AddScoped(typeof(IBillingServices<>), typeof(BillingServices));
// 注册IBillingServices
builder.Services.AddScoped<IBillingServices, BillingServices>();

//IOC（控制反转）和DI（依赖注入）
//IOC是一种思想，DI是实现这种思想的具体手段
//控制反转的好处：我们所用的方法不需要关心什么对象，由容器负责全部创建IOC容器
#region 依赖注入相关服务
/**
 * Transient: 瞬时，同一个请求中，即便注册多次，每次都是不同的实例对象
 * Scoped：  作用域，同一个请求中，即便注册多次，每次都是相同的实例对象
 * Singleton: 单例，程序整个的创建后，都是共享同一个实例对象，所有请求都是共享同一个实例直到程序停止
 */

//注册服务
builder.Services.AddTransient<IWorkflowService, WorkflowService>();
builder.Services.AddTransient<IUserService, UserService>();

builder.Services.AddScoped<StartStep>();
builder.Services.AddScoped<AuditStep>();
builder.Services.AddScoped<EndStep>();

builder.Services.AddDbContext<Workflow2211Context>();
//添加工作流相关服务 通过 AddWorkflow() 注册工作流引擎支持可视化设计和执行。
builder.Services.AddWorkflow(x =>
{
    //第二个参数是否自动创建数据库，第三个是否自动迁移，建议false
    x.UseMySQL(builder.Configuration.GetConnectionString("MySQL"), false, false);
});
//将json转换为引擎内部能够识别的代码（能够通过 JSON 配置工作流而不是硬编码）
builder.Services.AddWorkflowDSL();

//注册AutoMapper
builder.Services.AddAutoMapper(x => 
{
    x.AddProfile<WorkflowProfile>();
});
//注册雪花ID （WorkerId工作ID）
YitIdHelper.SetIdGenerator(new IdGeneratorOptions() { WorkerId =1 });

#endregion


// JWT Authentication 配置
var jwtSettings = builder.Configuration.GetSection("JwtSettings");

// 确保SecretKey存在
string secretKeyStr = jwtSettings["SecretKey"] ?? "1qaz2wsx3edc4rfv5tgb6yhn7ujm8ikl";
// 确保密钥长度至少为32字节(256位)，满足HS256算法要求
if (secretKeyStr.Length < 32)
{
    secretKeyStr = secretKeyStr.PadRight(32, '#');
}
Console.WriteLine($"JWT密钥: {secretKeyStr}, 长度: {secretKeyStr.Length}");

var secretKey = Encoding.UTF8.GetBytes(secretKeyStr);

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    
    // 添加JWT Bearer事件处理
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            Console.WriteLine("JWT Token收到: " + context.Request.Headers["Authorization"]);
            return Task.CompletedTask;
        },
        OnAuthenticationFailed = context =>
        {
            Console.WriteLine("JWT认证失败: " + context.Exception.Message);
            return Task.CompletedTask;
        },
        OnTokenValidated = context =>
        {
            Console.WriteLine("JWT令牌验证成功");
            return Task.CompletedTask;
        }
    };
    
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(secretKey),
        ValidateIssuer = true,
        ValidIssuer = jwtSettings["Issuer"],
        ValidateAudience = true,
        ValidAudience = jwtSettings["Audience"],
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero // 默认是5分钟，这里设置为0
    };
});
builder.Services.AddAuthorization();
//添加HTTP上下文访问器
builder.Services.AddHttpContextAccessor();

var app = builder.Build();

// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())//判断当前项目是否是开发环境
//{
        //IsDevelopment 开发环境
        //IsEnvironment 测试环境
        //IsProduction  生产环境
        //IsStaging     预发布环境
//    app.UseSwagger();
//    app.UseSwaggerUI();
//}
//启用 Swagger JSON 文档端点（默认：/swagger/v1/swagger.json）：
app.UseSwagger();
//设置可视化 Swagger UI（默认：/swagger/index.html）：
//app.UseSwaggerUI();

app.UseKnife4UI();

//app.UseWorkflow();

app.UseAuthentication(); // 认证中间件
//如果用户在尝试调用需要授权的接口（带有 [Authorize] 特性）时：
app.UseAuthorization();
//映射控制器路由，将 HTTP 请求地址映射到相应的控制器和动作
app.MapControllers();

app.UseCors(x=>x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());

//启动应用程序 Kestrel 服务器并处理 HTTP 请求：
app.Run();